// 目标：1.使用useRef在父组件中获取子组件的dom元素和调用其函数
//      2.区别useRef 在18版本 和 19版本使用方式不一样
//        v18 useRef函数不是必传参数
//        v19 useRef函数是必传参数
//        v19 暴露子组件的参数给父组件也不一样
//      3.useImperativeHandle的执行时机
//      语法： useImperativeHandle(ref, createHandle, dependencies?)

import { Divider, Button } from 'antd';
import React, { useImperativeHandle, useRef, useState } from 'react';

interface ChildRef {
  name: string;
  count: number;
  // style?: React.CSSProperties;
  addCount: () => void;
  subCount: () => void;
  getCount: () => number;
  getH4Dom: () => HTMLHeadingElement | null;
}

// 1-1.获取子组件的dom元素
// 子组件如何接收ref? 使用React.forwardRef函数包裹子组件。【比vue多了这个步骤React.forwardRef】
// 子组件函数的两个参数props和第二个参数ref。子组件ref属性值绑定的元素，会传递给父组件的ref参数。
// 1-2.调用子组件的函数和获取子组件的属性
// 前提是要子组件暴露出去 useImperativeHandle(ref, createHandle, dependencies?)
const Child = React.forwardRef<ChildRef>((props, ref) => {
  // 2. reactV19的用法：删除了React.forwardRef函数，将ref和props合并成一个参数，一起传递给子组件
  // const Child = ({ ref }: { ref: React.Ref<ChildRef> }) => {
  const [count, setCount] = useState(0);
  const h4Ref = useRef<HTMLHeadingElement>(null);
  const [flag, setFlag] = useState(true);
  useImperativeHandle(
    ref,
    () => {
      // 3.验证执行时机-dependencies?依赖性控制 同useEffect一样。3种执行时机：不传&[]&[指定状态]
      // 不传：组件加载完成时，useImperativeHandle执行一次。组件的状态值有变化就执行。
      // []：组件加载完成时，useImperativeHandle只执行一次，后续不执行。
      // [指定状态]：组件加载完成时，useImperativeHandle执行一次，指定的状态值更新才执行。

      console.log('useImperativeHandle');

      // 可以把属性、状态、函数暴露给父组件
      return {
        name: 'Child',
        count,
        addCount: () => setCount(count + 1),
        subCount: () => setCount(count - 1),
        getCount: () => count,
        getH4Dom: () => h4Ref.current,
      };
    },
    [count]
  );
  return (
    <div>
      {/* <h4 style={{ color: 'blue' }} ref={ref}>子组件</h4> */}
      {/* 以上ref属性绑定只能获取h4元素，不能获取子组件的属性和方法。使用useImperativeHandle要删除ref属性绑定，通过useImperativeHandle处理 */}
      <h4 style={{ color: 'blue' }} ref={h4Ref}>
        子组件
      </h4>
      <p>子组件详情信息</p>
      <p>count：{count}</p>
      <Button onClick={() => setCount(count + 1)}>+1</Button>
      <Button onClick={() => setCount(count - 1)}>-1</Button>
      <div>
        <p>flag状态：{flag ? 'true' : false}</p>
        <Button onClick={() => setFlag(!flag)}>改变flag状态</Button>
      </div>
    </div>
  );
});

const App = () => {
  const childRef = useRef<ChildRef>(null);
  const getChildDom = () => {
    // console.log(childRef.current);
    console.log(childRef.current?.getH4Dom(), 'getChildDom');
  };
  const setChildDom = () => {
    if (childRef.current) {
      // childRef.current?.style.color = 'red';
      // childRef.current.getH4Dom()?.style.color = 'red';
      const h4Element = childRef.current?.getH4Dom();
      if (h4Element) {
        h4Element.style.color = 'red';
      }
    }
  };
  const getChildInfo = () => {
    console.log(childRef.current);
  };
  return (
    <>
      <div>
        <h3>父组件</h3>
        <Button onClick={getChildDom}>获取子组件的h4元素</Button>
        <Button onClick={setChildDom}>改变子组件的h4元素字体颜色</Button>
        <Button onClick={getChildInfo}>获取子组件信息</Button>
        <div>
          <Button onClick={() => childRef.current?.addCount()}>子组件+1</Button>
          <Button onClick={() => childRef.current?.subCount()}>子组件-1</Button>
        </div>
        <Divider />
        <Child ref={childRef} />
      </div>
    </>
  );
};

export default App;
